home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / windows / ats113.zip / REXEC.C < prev    next >
C/C++ Source or Header  |  1996-01-14  |  20KB  |  858 lines

  1. /*
  2.  * Copyright (c) 1994-1996 Ataman Software, Inc.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  * 3. All advertising materials mentioning features or use of this software
  13.  *    must display the following acknowledgement:
  14.  *     This product includes software developed by Ataman Software, Inc.
  15.  * 4. The name of Ataman Software, Inc. may not may be used to endorse or
  16.  *    promote products derived from this software without specific prior
  17.  *    written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY ATAMAN SOFTWARE, INC. ``AS IS'' AND
  20.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22.  * ARE DISCLAIMED.  IN NO EVENT SHALL ATAMAN SOFTWARE, INC. BE LIABLE
  23.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29.  * SUCH DAMAGE.
  30.  */
  31.  
  32.  
  33. static char copyright[] =
  34.     "Copyright (c) 1994-1996 Ataman Software, Inc.  All rights reserved.";
  35.  
  36. /*
  37.  *  To compile this program for use under Windows NT or Windows 95 using
  38.  *  Microsoft Visual C++, rename the file rexec.c to rexec.cpp and then
  39.  *  use the following command:
  40.  *  cl -DWIN32 -O2 -D_MT /MT rexec.cpp libcmt.lib kernel32.lib advapi32.lib wsock32.lib
  41.  */
  42.  
  43. #ifdef WIN32
  44. #pragma warning(disable: 4699)
  45. /* Includes for Win32 systems go here. */
  46. #define STRICT
  47. #pragma warning(disable: 4201)
  48. #include <windows.h>
  49. #pragma warning(default: 4201)
  50. #include <winsock.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <process.h>
  55. #include <signal.h>
  56. #define RETVAL DWORD
  57. #define IDENT HANDLE
  58. #define STDINPUT hStdIn
  59. #define STDOUTPUT hStdOut
  60. #define STDERROR hStdErr
  61. #define FILECOOKIE HANDLE
  62.  
  63. static void PassInputThread(void *);
  64. static void PassOutputThread(void *);
  65. static void PassErrorThread(void *);
  66.  
  67. HANDLE hStdIn, hStdOut, hStdErr;
  68.  
  69. #else
  70. /* Includes for Unix systems go here. */
  71. #include <sys/types.h>
  72. #include <sys/socket.h>
  73. #include <sys/wait.h>
  74. #include <netinet/in.h>
  75. #include <netdb.h>
  76. #include <signal.h>
  77. #include <pwd.h>
  78. #include <stdio.h>
  79. #include <stdlib.h>
  80. #include <string.h>
  81. #include <errno.h>
  82. #include <sgtty.h>
  83. #define SOCKET int
  84. #define RETVAL int
  85. #define IDENT int
  86. #define INVALID_SOCKET (-1)
  87. #define SOCKET_ERROR (-1)
  88. #define WSAGetLastError() errno
  89. #define GetLastError() ((unsigned long)errno)
  90. #define closesocket(s) close(s)
  91. #define STDINPUT 0
  92. #define STDOUTPUT 1
  93. #define STDERROR 2
  94. #define FILECOOKIE int
  95. #define BOOL int
  96. #define TRUE 1
  97. #define FALSE 0
  98. #endif
  99.  
  100.  
  101.  
  102. /*
  103. Think carefully before enabling the -p option.  While it may be
  104. convenient to have this option, it is for many (if not most) sites a
  105. security hole.  Remember that the '-p password' used on the command
  106. line is visible on most Unix systems to any user that is allow to run
  107. the 'ps' command (normally ALL users can run this command).  While no
  108. utility that comes by default with Windows NT at this time, shows the
  109. same information, it is unclear whether or not the information is
  110. avaiable to all users.  Certainly privileged users would be be able to
  111. see this information on any system.
  112.  
  113. If the security risk is acceptable at your site, you can enable the -p
  114. option by uncommenting the #define below.
  115. */
  116. /* #define ALLOWDASH_P */
  117.  
  118. static void Usage(void);
  119.  
  120. static int NullStdIn;
  121. static char *GetUsername(void);
  122. static char *GetPassword(void);
  123. static void OpenService(const char *remote_host);
  124. static void Cleanup(void);
  125. static IDENT PassInput(void);
  126. static IDENT PassOutput(void);
  127. static IDENT PassError(void);
  128. static BOOL Close(FILECOOKIE);
  129. static int Read(FILECOOKIE, char *, size_t);
  130. static BOOL Write(FILECOOKIE, const char *, size_t);
  131. static BOOL Send(SOCKET, const char *, size_t);
  132. static BOOL SendZString(const char *);
  133. static BOOL GetErrString(char *, size_t);
  134. static void Wait(IDENT, RETVAL *);
  135.  
  136. static SOCKET sIO = INVALID_SOCKET;
  137. static SOCKET sErr = INVALID_SOCKET;
  138.  
  139. IDENT idIn = 0;
  140. IDENT idOut, idErr;
  141.  
  142. void main(int argc, char *argv[])
  143. {
  144.     char *hostname;
  145.     char *username;
  146.     char *password;
  147.     char command[4096];
  148.     size_t cmdlen;
  149.     int i;
  150.     RETVAL rvIn, rvOut, rvErr;
  151.  
  152.     if (argc < 3) {
  153.         Usage();
  154.     }
  155.  
  156. #ifdef WIN32
  157.     hStdIn = GetStdHandle(STD_INPUT_HANDLE);
  158.     hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  159.     hStdErr = GetStdHandle(STD_ERROR_HANDLE);
  160. #endif
  161.  
  162.     hostname = argv[1];
  163.     password = NULL;
  164.     username = NULL;
  165.  
  166.     for (i=2; i<argc; i++) {
  167.         if (*argv[i] != '-') {
  168.             break;
  169.         } else if (strcmp(argv[i], "--") == 0) {
  170.             i++;
  171.             break;
  172.         } else if (strcmp(argv[i], "-n") == 0) {
  173.             NullStdIn = 1;
  174.         } else if (strcmp(argv[i], "-l") == 0) {
  175.             username = argv[++i];
  176.         } else if (strcmp(argv[i], "-p") == 0) {
  177. #ifdef ALLOWDASH_P
  178.             password = argv[++i];
  179. #else
  180.             fprintf(stderr,
  181.                 "The -p option is a potential security hole, "
  182.                 "please see the comments in the source code\n"
  183.                 "before enabling this feature.\n");
  184.             exit(1);
  185. #endif
  186.         } else {
  187.             Usage();
  188.         }
  189.     }
  190.  
  191.     if (i >= argc) {
  192.         Usage();
  193.     }
  194.  
  195.     *command = '\0';
  196.  
  197.     cmdlen = 0;
  198.     for (; i<argc; i++) {
  199.         size_t arglen;
  200.  
  201.         arglen = strlen(argv[i]);
  202.         if (cmdlen+arglen+2 > sizeof command) {
  203.             fprintf(stderr, "Command too long.\n");
  204.             exit(1);
  205.         }
  206.         strcpy(&command[cmdlen], argv[i]);
  207.         strcpy(&command[cmdlen+arglen], " ");
  208.         cmdlen += arglen+1;
  209.     }
  210.  
  211.     if (!username) {
  212.         username = GetUsername();
  213.     }
  214.  
  215.     if (!password) {
  216.         password = GetPassword();
  217.     }
  218.  
  219.     OpenService(hostname);
  220.  
  221.     SendZString(username);
  222.     SendZString(password);
  223.     memset (password, '\0', strlen(password));
  224.     SendZString(command);
  225.  
  226.     if (!GetErrString(command, sizeof command)) {
  227.         fprintf(stderr, "Remote aborted connection without initiating protocol: %d.\n",
  228.             WSAGetLastError());
  229.         exit(1);
  230.     }
  231.  
  232.     if (*command != '\0') {
  233.         char *p = command;
  234.         if (*p == '\001') {
  235.             p++;
  236.         }
  237.         fprintf(stderr, "Remote aborted connection: %s\n", p);
  238.         exit(1);
  239.     }
  240.  
  241.     if (!NullStdIn) {
  242.         idIn = PassInput();
  243.     } else {
  244.         if (!Close(STDINPUT)) {
  245.             fprintf(stderr, "Failed to close standard input: error = %lu.\n",
  246.                 GetLastError());
  247.             exit(1);
  248.         }
  249.  
  250.         if (shutdown(sIO, 1) == SOCKET_ERROR) {
  251.             fprintf(stderr, "Failed to shutdown from input socket: error = %d.\n",
  252.                 WSAGetLastError());
  253.             exit(1);
  254.         }
  255.     }
  256.  
  257.     idOut = PassOutput();
  258.     idErr = PassError();
  259.  
  260.     if (!NullStdIn) {
  261.         Wait(idIn, &rvIn);
  262.     } else {
  263.         rvIn = 0;
  264.     }
  265.     Wait(idOut, &rvOut);
  266.     Wait(idErr, &rvErr);
  267.  
  268.     exit((int)(rvIn | rvOut | rvErr));
  269. }
  270.  
  271.  
  272. static char *GetUsername()
  273. {
  274.     static char username[1024];
  275. #ifdef WIN32
  276.     unsigned char tubuf[1024];
  277.     char chDomain[510];
  278.     TOKEN_USER *ptu = (TOKEN_USER *)tubuf;
  279.     SID_NAME_USE snu;
  280.     DWORD cbUser, cbDomain, cbDummy;
  281.     HANDLE hAccessToken;
  282.  
  283.     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hAccessToken)) {
  284.         fprintf(stderr, "Can't open process token: error = %lu.\n", GetLastError());
  285.         exit(1);
  286.     }
  287.  
  288.     if (!GetTokenInformation(hAccessToken, TokenUser, ptu, sizeof tubuf, &cbDummy)) {
  289.         fprintf(stderr, "Can't get user sid: error = %lu.\n", GetLastError());
  290.         exit(1);
  291.     }
  292.  
  293.     cbUser = sizeof username;
  294.     cbDomain = sizeof chDomain;
  295.     if (!LookupAccountSid(NULL, ptu->User.Sid, username, &cbUser, chDomain, &cbDomain, &snu)) {
  296.         fprintf(stderr,